/*
 * Copyright (c) 2006-2019, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-05-24                  the first version
 */

#include <rthw.h>
#include <rtthread.h>

#include "main.h"

#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
/*
 * Please modify RT_HEAP_SIZE if you enable RT_USING_HEAP
 * the RT_HEAP_SIZE max value = (sram size - ZI size), 1024 means 1024 bytes
 */
#define RT_HEAP_SIZE (1024 * 8)
static uint8_t rt_heap[RT_HEAP_SIZE]; // heap default size: 4K(1024 * 4)

RT_WEAK void *rt_heap_begin_get(void) { return rt_heap; }

RT_WEAK void *rt_heap_end_get(void) { return rt_heap + RT_HEAP_SIZE; }
#endif

void SysTick_Handler(void)
{
    rt_interrupt_enter();

    rt_tick_increase();

    rt_interrupt_leave();
}

#ifdef RT_USING_FINSH
#include <finsh.h>
static void reboot(uint8_t argc, char **argv) { rt_hw_cpu_reset(); }
MSH_CMD_EXPORT(reboot, Reboot System);
#endif /* RT_USING_FINSH */

void SystemClockConfig(void)
{
    /* Enable HSE */
    LL_RCC_HSE_SetFreqRegion(LL_RCC_HSE_4_8MHz);

    LL_RCC_HSE_Enable();
    while (LL_RCC_HSE_IsReady() != 1)
    {
    }
    /* Configure PLL */
    LL_RCC_PLL_Disable();
    while (LL_RCC_PLL_IsReady() != 0)
    {
    }
    LL_RCC_PLL_SetMainSource(LL_RCC_PLLSOURCE_HSE);
    LL_RCC_PLL_SetMulFactor(LL_RCC_PLLMUL_18); // 8 * 18 = 144
    LL_RCC_PLL_Enable();
    while (LL_RCC_PLL_IsReady() != 1)
    {
    }
    /* Set flash latency */
    LL_FLASH_SetLatency(LL_FLASH_LATENCY_6);
    while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_6)
    {
    }

    /* Select PLL as system clock source, and if it goes over or under 80Mhz,
    it is necessary to use HCLK prescaler 2 for intermediate steps */
    LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2);
    LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);

    LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
    LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
    LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);

    SystemCoreClockUpdate();
}

/**
 * This function will initial your board.
 */
void rt_hw_board_init(void)
{
    SystemClockConfig();

    LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG);
    LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);
    NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_3);

    /*
     * 1: OS Tick Configuration
     * Enable the hardware timer and call the rt_os_tick_callback function
     * periodically with the frequency RT_TICK_PER_SECOND.
     */
    SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);

    /* Call components board initial (use INIT_BOARD_EXPORT()) */
#ifdef RT_USING_COMPONENTS_INIT
    rt_components_board_init();
#endif

#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
    rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());
#endif
}
